---
id: dmtpremotestream
title: b.远程流映射
---

import Tag from "@site/src/components/Tag.js";

### 定义

命名空间：TouchSocket.Dmtp <br/>
程序集：[TouchSocketPro.Dmtp.dll](https://www.nuget.org/packages/TouchSocketPro.Dmtp)



## 一、说明 <Tag>Pro</Tag>

可以在通信对方，创建一个Stream，然后映射到本地，由本地直接进行读、写等操作。


## 二、场景

当远程主机拥有一个超大流数据（可能是文件，或者其他）时，本地只想访问其部分数据的话，就可以使用该功能。
例如，假设C服务器有个10Gb的文件。A客户端需要其10000-20000字节之间的数据，那你此时可以使用该功能，直接进行读取。


## 三、使用

该功能由`DmtpRemoteStreamFeature`功能插件提供。所以需要`客户端`和`服务器`都需要`UseDmtpRemoteStream`。

```csharp showLineNumbers
.ConfigurePlugins(a =>
{
    a.UseDmtpRemoteStream();
});
```


【请求端】
任意Dmtp终端均可以调用LoadRemoteStream创建一个流数据映射。
同时可以传递一个元数据组。用于载入自定义消息。

```csharp showLineNumbers
var metadata = new Metadata();
metadata.Add("tag", "tag1");

var remoteStream = client.GetDmtpRemoteStreamActor().LoadRemoteStream(metadata);
```

【响应端】
响应端定义一个插件，实现`IDmtpRemoteStreamPlugin`，然后实现需要载入的具体流信息。示例中是以`MemoryStream`作为流主体。

```csharp showLineNumbers
internal class MyRemoteStreamPlugin : PluginBase, IDmtpRemoteStreamPlugin<ITcpDmtpSocketClient>
{
    public async Task OnLoadingStream(ITcpDmtpSocketClient client, LoadingStreamEventArgs e)
    {
        if (e.Metadata["tag"] == "tag1")
        {
            e.IsPermitOperation = true;//需要允许操作

            client.Logger.Info("开始载入流");
            //当请求方请求映射流的时候，会触发此方法。
            using (var stream = new MemoryStream())
            {
                await e.WaitingLoadStreamAsync(stream, TimeSpan.FromSeconds(60));

                client.Logger.Info($"载入的流已被释放，流中信息：{Encoding.UTF8.GetString(stream.ToArray())}");
            }

            return;
        }

        //如果不满足，调用下一个插件
        await e.InvokeNext();
    }
}
```

## 四、读写

当RemoteStream被成功创建以后，即可直接Read、Write。因为RemoteStream继承自Stream。

```csharp showLineNumbers
var client = GetClient();
var remoteStream = client.GetDmtpRemoteStreamActor().LoadRemoteStream(new Metadata().AddOrUpdate("1", "1"));

byte[] data = new byte[] { 0, 1, 2, 3, 4 };
remoteStream.Write(data);

remoteStream.Position = 0;
byte[] buffer=new byte[5];
remoteStream.Read(buffer);

remoteStream.SafeDispose();
```

## 五、释放

当**断开连接**，或者请求方主动调用Dispose时，响应方的Stream均会被实际的Dispose掉。


## 六、性能

图中示例为直接读取一个Window.iso文件所示。

<img src={require('@site/static/img/docs/remotestreamaccess-1.gif').default} />

[本文示例Demo](https://gitee.com/RRQM_Home/TouchSocket/tree/master/examples/Dmtp/RemoteStreamConsoleApp)
